`include "../include/cpu_defines.sv"
`include "../include/common.sv"

module Btb #(
	parameter INDEX_SIZE=6,
	parameter TAG_SIZE=30
)(
	input logic cpu_clk,
	input logic cpu_rst_n,
	input logic clear,
	input logic [INDEX_SIZE-1: 0] search_index,
	input logic [TAG_SIZE-1: 0] search_tag,
	input logic update_en,
	input logic update_delay,
	input logic [INDEX_SIZE-1: 0] update_index,
	input logic [TAG_SIZE-1: 0] update_tag,
	input logic [31: 0] update_addr,
	output logic out_en, // 当前表项是否命中
	output logic out_delay,
	output logic [31: 0] out_addr
);
	logic [TAG_SIZE+33: 0] update_ele_out, search_out;
	logic [`LSHIFTX(INDEX_SIZE)-1: 0] en;
	logic search_hit;
	SDPRAM #(
		.WORD_WIDTH(TAG_SIZE + 34),
		.DEPTH(`LSHIFTX(INDEX_SIZE)),
		.ADDR_WIDTH(INDEX_SIZE)
	) ram(
		.clk(cpu_clk),
		.ena(update_en),
		.addra(update_index),
		.wea(update_en),
		.dina({1'b1, update_delay, update_tag, update_addr}),
		.douta(update_ele_out),
		.enb(1'b1),
		.addrb(search_index),
		.doutb(search_out)
	);

	always_ff @(posedge cpu_clk)begin
		if(cpu_rst_n == 1'b0 || clear)begin
			en <= 0;
		end
		else begin
			if(update_en)begin
				en[update_index] <= 1'b1;
			end
		end
	end

	assign search_hit = search_tag == search_out[TAG_SIZE+31: 32];
	assign out_delay = search_out[TAG_SIZE+32];
	assign out_en = en[search_index] && search_hit;
	assign out_addr = search_out[31: 0];
endmodule